from fastapi import APIRouter, HTTPException, Depends
from sqlalchemy.exc import SQLAlchemyError

from db.controller.db_controller import db_controller
from enums.modbus_funcode import ModbusFunctionCode
from enums.modbus_register import RegisterType
from web.dependencies import get_server_manager
from web.log import log
from web.model.slave import Slave, SlaveIdList, SlaveAddress, SlaveInfo, WriteRegister
from service.client.client_manager import client_manager

# 创建路由对象
slave_router = APIRouter()


@slave_router.post('/add_slave')
async def add_slave(body: Slave, server_manager=Depends(get_server_manager)):
    device_name = body.device_name
    slave_id = body.slave_id
    try:
        if server_manager.is_slave_exist(device_name, slave_id):
            return {'status': 500, 'msg': '添加从机失败, 从机已存在', 'data': False}

        if db_controller.slave_dao.add_slave(device_name, slave_id):
            server_manager.add_slave(device_name, slave_id)
        else:
            return {'status': 500, 'msg': '添加从机失败', 'data': False}
    except SQLAlchemyError as e:
        log.error(f"数据库操作失败: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'数据库错误: {e}', 'data': False})
    except Exception as e:
        log.error(f"未知错误: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'服务器内部错误: {e}', 'data': False})


@slave_router.post('/delete_slave')
async def delete_slave(body: Slave, server_manager=Depends(get_server_manager)):
    device_name = body.device_name
    slave_id = body.slave_id
    try:
        if db_controller.slave_dao.delete_slave(device_name, slave_id):
            server_manager.delete_slave(device_name, slave_id)
            return {'status': 200, 'msg': '删除从机成功', 'data': True}
        else:
            return {'status': 500, 'msg': '删除从机失败', 'data': False}
    except SQLAlchemyError as e:
        log.error(f"数据库操作失败: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'数据库错误: {e}', 'data': False})
    except Exception as e:
        log.error(f"未知错误: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'服务器内部错误: {e}', 'data': False})


@slave_router.post('/get_slave_id_list')
async def get_slave_id_list(body: SlaveIdList):
    device_name = body.device_name
    try:
        result = db_controller.slave_dao.get_slave_id_list(device_name)
        return {'status': 200, 'msg': '获取从机ID列表成功', 'data': result}
    except SQLAlchemyError as e:
        log.error(f"数据库操作失败: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'数据库错误: {e}', 'data': []})
    except Exception as e:
        log.error(f"未知错误: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'服务器内部错误: {e}', 'data': []})


@slave_router.post('/set_slave_address')
async def set_slave_address(body: SlaveAddress, server_manager=Depends(get_server_manager)):
    device_name = body.device_name
    slave_id = body.slave_id
    register_type = body.register_type
    start_address = body.start_address
    end_address = body.end_address
    try:
        if db_controller.slave_dao.set_slave_address(device_name, slave_id, register_type, start_address, end_address):
            server_manager.set_slave_address(device_name, slave_id, register_type, start_address, end_address)
            return {'status': 200, 'msg': '设置从机寄存器地址成功', 'data': True}
        else:
            return {'status': 500, 'msg': '设置从机寄存器地址失败', 'data': False}
    except SQLAlchemyError as e:
        log.error(f"数据库操作失败: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'数据库错误 {e}', 'data': False})
    except Exception as e:
        log.error(f"未知错误: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'服务器内部错误 {e}', 'data': False})


@slave_router.post('/get_slave_table')
async def get_slave_table(body: SlaveInfo, server_manager=Depends(get_server_manager)):
    device_name = body.device_name
    slave_id = body.slave_id
    register_type = body.register_type
    try:
        device = db_controller.device_dao.is_device_exist(device_name)
        if device is None:
            return {'status': 200, 'msg': f'无法找到该设备:{device_name}!', 'data': []}
        start_address, end_address = db_controller.slave_dao.get_slave_address(device_name, slave_id, register_type)
        if start_address == -1 or end_address == -1:
            return {'status': 200, 'msg': f'寄存器地址未设置!', 'data': []}

        result = list(range(start_address, end_address + 1))
        return {'status': 200, 'msg': '获取从机表数据成功', 'data': result}
    except SQLAlchemyError as e:
        log.error(f"数据库操作失败: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'数据库错误 {e}', 'data': []})
    except Exception as e:
        log.error(f"未知错误: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': f'服务器内部错误 {e}', 'data': []})


@slave_router.post('/write_register')
async def write_register(body: WriteRegister):
    device_name = body.device_name
    slave_id = body.slave_id
    register_type = body.register_type
    start_address = body.start_address
    data_type = body.data_type
    value_list = body.value_list
    write_func = body.write_func
    try:
        client = client_manager.get_client(device_name)

        is_success = False
        if register_type == RegisterType.COIL:
            if write_func == ModbusFunctionCode.WRITE_COIL_REGISTERS:
                is_success = client.write_single_coil_register(slave_id=slave_id, start_address=start_address,
                                                               value_list=value_list)
            else:
                is_success = client.write_coil_registers(slave_id=slave_id, start_address=start_address,
                                                         value_list=value_list)
        elif register_type == RegisterType.HOLDING_REGISTER:
            if write_func == ModbusFunctionCode.WRITE_HOLDING_REGISTERS:
                is_success = client.write_single_holding_register(slave_id=slave_id, start_address=start_address,
                                                                  data_type=data_type, value_list=value_list)
            else:
                is_success = client.write_holding_registers(slave_id=slave_id, start_address=start_address,
                                                            data_type=data_type, values=value_list)
        if is_success:
            return {'status': 200, 'msg': '写入寄存器成功!', 'data': is_success}
        else:
            raise HTTPException(status_code=500, detail={'status': 500, 'msg': '写入寄存器失败!', 'data': is_success})
    except SQLAlchemyError as e:
        log.error(f"数据库操作失败: {e}")
        raise HTTPException(status_code=500, detail={'status': 500, 'msg': '写入寄存器失败, 数据库错误', 'data': False})
    except Exception as e:
        log.error(f"未知错误: {e}")
        raise HTTPException(status_code=500,
                            detail={'status': 500, 'msg': '写入寄存器失败, 服务器内部错误', 'data': False})
